#include "altabstractmapeditor.h"

#include "altapplication.h"
#include "altmap.h"
#include "altmapeditorplugin.h"

#include <QAction>
#include <QDataStream>
#include <QFile>
#include <QFileDialog>
#include <QMenu>
#include <QMenuBar>
#include <QMessageBox>

namespace Alt {
     AbstractMapEditor::AbstractMapEditor(QWidget* parent) : QMainWindow(parent) {
          m_fileMenu = menuBar()->addMenu(tr("&File"));

          m_fileNewMenu = m_fileMenu->addMenu(QIcon(":/fileNew.svg"), tr("&New"));
          foreach(QString mapType, Map::allEditableMapTypes()){
               QMenu* menu = m_fileNewMenu->addMenu(mapType);
               foreach(MapEditorPlugin* editorPlugin, Application::findMapEditorPlugins(mapType)){
                    QAction* action = menu->addAction(editorPlugin->pluginName());
                    action->setProperty("map type", mapType);
                    action->setProperty("map editor plugin", (int)editorPlugin);
                    action->setStatusTip(tr("Create a new %1 using this plugin.").arg(mapType));
               }
          }
          connect(m_fileNewMenu, SIGNAL(triggered(QAction*)), this, SLOT(fileNew(QAction*)));

          m_fileOpenAction = m_fileMenu->addAction(QIcon(":/fileOpen.svg"), tr("&Open"));
          m_fileOpenAction->setStatusTip(tr("Opens an existing map."));
          m_fileOpenAction->setShortcut(QKeySequence::Open);
          m_fileOpenAction->setShortcutContext(Qt::WidgetShortcut);
          connect(m_fileOpenAction, SIGNAL(triggered()), this, SLOT(fileOpen()));

          m_fileSaveAction = m_fileMenu->addAction(QIcon(":/fileSave.svg"), tr("&Save"));
          m_fileSaveAction->setStatusTip(tr("Saves the current map."));
          m_fileSaveAction->setShortcut(QKeySequence::Save);
          m_fileSaveAction->setShortcutContext(Qt::WidgetShortcut);
          connect(m_fileSaveAction, SIGNAL(triggered()), this, SLOT(fileSave()));

          m_fileSaveAsAction = m_fileMenu->addAction(QIcon(":/fileSaveAs.svg"), tr("Save &as"));
          m_fileSaveAsAction->setStatusTip(tr("Saves the current map under a new name."));
          m_fileSaveAsAction->setShortcut(QKeySequence::SaveAs);
          m_fileSaveAsAction->setShortcutContext(Qt::WidgetShortcut);
          connect(m_fileSaveAsAction, SIGNAL(triggered()), this, SLOT(fileSaveAs()));

          m_fileMenu->addSeparator();

          m_fileCloseAction = m_fileMenu->addAction(QIcon(":/fileClose.svg"), tr("&Close"));
          m_fileCloseAction->setStatusTip(tr("Closes this window."));
          m_fileCloseAction->setShortcutContext(Qt::WidgetShortcut);
          m_fileCloseAction->setShortcut(QKeySequence::Close);
          connect(m_fileCloseAction, SIGNAL(triggered()), this, SLOT(close()));
     }

     AbstractMapEditor::~AbstractMapEditor() {
     }

     //private slots
     void AbstractMapEditor::fileNew(QAction* action) {
          QString mapType = action->property("map type").toString();
          MapEditorPlugin* mapEditorPlugin = (MapEditorPlugin*)action->property("map editor plugin").toInt();
          if(!mapType.isEmpty()){
               AbstractMapEditor* editor = mapEditorPlugin->createMapEditor(mapType, "", 0);
               editor->setWindowFlags(Qt::Window);
               editor->setAttribute(Qt::WA_DeleteOnClose, true);
               editor->show();
          }
          return;
     }

     void AbstractMapEditor::fileOpen() {
          QString fileName = QFileDialog::getOpenFileName(this, tr("Open"), QString(), tr("All files (*.*)"));
          QFile file(fileName);
          if(!file.open(QIODevice::ReadOnly)){
               QMessageBox::critical(this, tr("Error opening file"), file.errorString());
               return;
          }
          QDataStream stream(&file);
          QString mapType;
          stream >> mapType;
          file.close();

          QList<MapEditorPlugin*> mapEditorPlugins = Application::findMapEditorPlugins(mapType);
          if(mapEditorPlugins.isEmpty()){
               QMessageBox::critical(this, tr("Error opening file"), tr("No suitable map editor plugin was found for this type of map."));
          } else if(mapEditorPlugins.size() == 1){
               AbstractMapEditor* editor = mapEditorPlugins[0]->createMapEditor(mapType, fileName, 0);
               editor->setWindowFlags(Qt::Window);
               editor->setAttribute(Qt::WA_DeleteOnClose, true);
               editor->setWindowFilePath(fileName);
               editor->show();
          } else {
               //@TODO
          }
          return;
     }

     void AbstractMapEditor::fileSave() {
          if(windowFilePath() == ""){
               fileSaveAs();
          } else {
               QFile file(windowFilePath());
               if(!file.open(QIODevice::WriteOnly)){
                    QMessageBox::critical(this, tr("Error saving file."), file.errorString());
                    return;
               }
               QDataStream stream(&file);
               Q_ASSERT_X(map() != 0, "saving map file", "map is null");
               if(!map()->save(stream)){
                    QMessageBox::critical(this, tr("Error saving file."), tr("Unknown error."));
               }
          }
          return;
     }

     void AbstractMapEditor::fileSaveAs() {
          QString filter = defaultFileFilter();
          if(filter != ""){
               filter += ";;";
          }
          filter += tr("All files (*.*)");

          QString startingPath = (windowFilePath() == "") ? QDir::homePath() : windowFilePath();

          QString selectedFilter = defaultFileFilter();
          QString fileName = QFileDialog::getSaveFileName(this, tr("Save as"), startingPath, filter, &selectedFilter);
          if(fileName != ""){
               if(selectedFilter != tr("All files (*.*)")){
                    //Append the selected file extension if the user did not do it.
                    QRegExp regexp("[^\\(]*\\(\\*(\\.\\w+)\\)");
                    regexp.lastIndexIn(selectedFilter);
                    QString fileExtension = regexp.cap(1);
                    if(!fileName.endsWith(fileExtension)){
                         fileName += fileExtension;
                    }
               }
               setWindowFilePath(fileName);
               fileSave();
          }
          return;
     }
}

